package com.tanhua.gateway.filters;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 网关过滤器：
 *  1、实现两个接口
 *  2、实现两个方法
 *  3、过滤器交给容器管理
 *  4、在filter方法中完成过滤器的核心处理逻辑
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    //读取配置文件，会自动的获取配置字符串，如果字符串中有“，”隔开，自动构建list集合
    @Value("${gateway.excludedUrls}")
    private List<String> excludeUrls; //定义了所有不需要token检验的URL集合

    /**
     * 过滤器的业务逻辑
     *  exchange：请求上下文--获取request，response
     *  chain：过滤器链 -- 请求放行
     */
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        //1、获取请求连接
        String path = request.getURI().getPath();   // login
        //2、判断此连接是否需要经过，token验证
        if(excludeUrls.contains(path)) {
            //2.1、如果不需要验证，路由到服务
            return chain.filter(exchange);
        }
        //3、获取到token  (手机端的token=token，页面token=Bearer token)
        String token = request.getHeaders().getFirst("Authorization");
        if(!StringUtils.isEmpty(token)) {
            token = token.replaceAll("Bearer ",""); //针对页面端的token问题
        }
        //4、调用工具类验证token
        boolean verifyToken = JwtUtils.verifyToken(token);
        //4.1 验证通过，路由到服务
        if(verifyToken) {
            return chain.filter(exchange);
        }else {
            //4.2 验证不通过，响应401
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //return response.setComplete(); //响应结束
            //携带响应数据（工作问题）
            Map<String,Object> map = new HashMap<>();
            map.put("errCode", 401);
            map.put("errMessage", "用户未登录");
            //databuffer
            //指定相应的数据头
            response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
            //需要将返回的对象数据转化为byte数组
            byte[] data = JSON.toJSONBytes(map);
            //构造DataBuffer对象
            DataBuffer buffer = response.bufferFactory().wrap(data); //数据DatBuffer
            return response.writeWith(Mono.just(buffer));
        }
    }

    //执行在过个过滤器（过滤器链）中的执行顺序
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;  //返回值越小，优先级越高
    }
}
